package com.enjoyor.health.HGPT.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.enjoyor.health.HGPT.core.config.ParamConfig;
import com.enjoyor.health.HGPT.core.dto.*;
import com.enjoyor.health.HGPT.core.entity.HealthIndicatorInfo;
import com.enjoyor.health.HGPT.core.entity.ReportData;
import com.enjoyor.health.HGPT.core.entity.ReportRecord;
import com.enjoyor.health.HGPT.core.enums.ReportDataType;
import com.enjoyor.health.HGPT.core.enums.RiskLevel;
import com.enjoyor.health.HGPT.core.service.IHealthIndicatorInfoService;
import com.enjoyor.health.HGPT.core.service.IReportDataRobotService;
import com.enjoyor.health.HGPT.core.service.IReportDataService;
import com.enjoyor.health.HGPT.core.service.IReportRecordService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.TextStyle;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author Zhu Min
 * @date 2023/10/24 13:43
 */
@Slf4j
@Service
public class BizReportService {
    @Autowired
    private IReportRecordService reportRecordService;
    @Autowired
    private IReportDataService reportDataService;
    @Autowired
    private ParamConfig paramConfig;
    @Autowired
    private IReportDataRobotService reportDataRobotService;
    @Autowired
    private IHealthIndicatorInfoService healthIndicatorInfoService;

    public String reportDownload(String openId, String version) {
        List<ReportRecord> reportRecordList = reportRecordService.getReportRecordByOpenId(openId, version, 1);
        String path = paramConfig.getDefaultReportPath();
        if (CollUtil.isNotEmpty(reportRecordList)) {
            path = paramConfig.getPdfPath() + reportRecordList.get(0).getId() + ".pdf";
        } else {
            log.info("report_download接口-用户{} {}本地不存在报告！", openId, version);
        }
        if (!FileUtil.exist(path)) {
            path = paramConfig.getDefaultReportPath();
        }
        return path;
    }

    /**
     * 编写 SQL 查询语句，根据 user_id 和 version 在 report_record 表中获取对应的 report_id。
     * 编写 SQL 查询语句，根据 report_id 在 report_data 表中获取所有数据。
     * 编写 SQL 查询语句，查询 user_info 表中的 name、age 和 gender 字段。
     * 根据 user_id 和 version 在 report_record 表中获取 update_time 字段。
     * 根据 user_id 和 version 在 report_record 表中统计该用户的报告数量。
     * 编写 Python 代码，将表 A、B 和 C 关联起来，并按照 body_part_name 分组，遍历每个分组，计算 organ、result 和 advice 字段。
     * 构造返回结果，并返回给前端。
     * 获取指定用户指定版本的所有检查部位和对应的器官名称
     */
    public JSONObject getMedicalReportData(String openId, String version, String type, Integer packageType) {
        JSONObject result = new JSONObject();
        List<ReportRecord> reportRecord = reportRecordService.getReportRecordByOpenId(openId, version, packageType);
        if (CollUtil.isEmpty(reportRecord)) {
            return new JSONObject();
        }
        String reportId = reportRecord.get(0).getId();
        String reportVersion = version;
        if (StringUtils.isNotBlank(reportRecord.get(0).getVersion())) {
            if (StringUtils.isBlank(version)) {
                reportVersion = reportRecord.get(0).getVersion();
            }
        } else {
            log.info("最新记录 version 不存在：'{}", openId);
        }

        if (StringUtils.isBlank(type)) {
            log.info("type is null");
        } else if ("0".equals(type)) {
            ReportUserDto reportUserDto = reportRecordService.getReportByUser(openId, reportVersion, packageType);
            List<ReportBayaDto> reportBayaDto = reportDataService.getReportBayaByReportId(reportId);

            String examResult = "本次检测暂未发现异常指标";
            JSONArray examResultDetail = new JSONArray();
            JSONArray abnormalDetail = new JSONArray();

            if (CollUtil.isNotEmpty(reportBayaDto)) {
                examResult = "本次检测发现异常指标，如您身体感到明显不适，请及早进行专业的健康指导或医疗服务";
                reportBayaDto = reportBayaDto.stream().sorted((x1, x2) -> x2.getValueRank() - x1.getValueRank()).collect(Collectors.toList());
                for (ReportBayaDto bayaDto : reportBayaDto) {
                    if (bayaDto.getValueRank() != null && bayaDto.getValueRank() > 0) {
                        String rankName = levelDescribe(bayaDto.getValueRank() + "");
                        examResultDetail.add(bayaDto.getItemName() + "-" + bayaDto.getValueRank() + "级-" + rankName);
                        JSONObject abnormalDetailResult = new JSONObject();
                        abnormalDetailResult.put("diseaseName", bayaDto.getItemName());
                        abnormalDetailResult.put("rank", bayaDto.getValueRank() - 1);
                        abnormalDetailResult.put("titleRank", bayaDto.getValueRank());
                        abnormalDetailResult.put("rankLowLimit", "1级");
                        abnormalDetailResult.put("rankHighLimit", "5级");
                        abnormalDetailResult.put("rankNum", 5);
                        abnormalDetailResult.put("rankName", rankName);
                        abnormalDetailResult.put("advice", bayaDto.getAdviceAbnormal());
                        abnormalDetailResult.put("medicalInterpretation", bayaDto.getContent());
                        abnormalDetailResult.put("rankDetail", "请注意！您的检测结果显示您可能患有" + bayaDto.getItemName() +
                                "，已经达到" + bayaDto.getValueRank() + "级，" + levelDescribe(bayaDto.getValueRank() + "") + "。");
                        abnormalDetail.add(abnormalDetailResult);
                    }
                }
            }
            result.put("abnormalDetail", abnormalDetail);
            result.put("examResultDetail", examResultDetail);
            result.put("examResult", examResult);
            result.put("age", reportUserDto.getAge());
            result.put("gender", reportUserDto.getGender());
            result.put("moreThan", 80);
            result.put("name", reportUserDto.getName());
            result.put("score", reportUserDto.getResultScore());
            result.put("time", reportUserDto.getInspectDate());
            return result;
        } else if ("1".equals(type)) {
            List<ReportDataScoreDto> reportDataScoreDtoList = reportDataService.getReportDataScoreDtoByReportId(reportId);
            List<String> mainSystemList = Lists.newArrayList("sysBrain", "sysCardiac", "sysEndocrin", "sysRespiratory", "sysDigestive",
                    "sysHepatobiliary", "sysUrinary", "sysIntestinal", "sysGynecological");
            List<String> biochemicalList = Lists.newArrayList("bioImmunobiochemistry", "bioBloodGlucose", "bioBlood", "bioThyroid", "bioUrinary", "bioTumor");
            //systemRadarList
            JSONArray systemRadar = new JSONArray();
            List<JSONObject> systemRadarList = reportDataScoreDtoList.stream().filter(x -> mainSystemList.contains(x.getNameEn()))
                    .collect(Collectors.toMap(ReportDataScoreDto::getNameEn, reportDataScoreDto -> reportDataScoreDto, (k1, k2) -> k1))
                    .values()
                    .stream().map(x -> {
                        JSONObject o = new JSONObject();
                        o.put("name", x.getName());
                        o.put("value", x.getValue());
                        o.put("max", 100);
                        return o;
                    }).collect(Collectors.toList());
            systemRadar.addAll(systemRadarList);
            //systemAssessmentList
            Map<String, List<ReportDataScoreDto>> riskMap =
                    reportDataScoreDtoList.stream().filter(x -> mainSystemList.contains(x.getNameEn()) && x.getValueRank() > 0)
                            .collect(Collectors.groupingBy(ReportDataScoreDto::getNameEn));
            JSONArray systemAssessmentArray = new JSONArray();
            for (String s : mainSystemList) {
                List<ReportDataScoreDto> riskList = riskMap.get(s);
                if (riskList != null && riskList.size() > 0) {
                    riskList = riskList.stream().sorted((x1, x2) -> x2.getScoreRank() - x1.getScoreRank()).collect(Collectors.toList());
                    ReportDataScoreDto riskDto = riskList.get(0);
                    JSONObject o = new JSONObject();
                    o.put("name", riskDto.getName());
                    o.put("nameEn", riskDto.getNameEn());
                    o.put("rank", riskDto.getScoreRank());
                    o.put("rankName", levelDescribe(riskDto.getScoreRank() + ""));
                    o.put("score", riskDto.getValue());
                    o.put("statement",
                            String.format("%s的本次结果为%s，请您继续努力。其中%s项疾病风险，%s项器官风险需关注，您可进入详情查看具体情况。如身体感到明显不适，请及早进行专业的健康指导或医疗服务。"
                                    , riskDto.getName(), levelDescribe(riskDto.getScoreRank() + ""), riskList.size(),
                                    riskList.stream().collect(Collectors.toMap(ReportDataScoreDto::getOrganName, reportDataScoreDto -> reportDataScoreDto, (k1, k2) -> k1)).size()));
                    systemAssessmentArray.add(o);
                } else {
                    reportDataScoreDtoList.stream().filter(x -> s.equals(x.getNameEn())).findFirst()
                            .ifPresent(x -> {
                                JSONObject o = new JSONObject();
                                o.put("name", x.getName());
                                o.put("nameEn", x.getNameEn());
                                o.put("rank", x.getScoreRank());
                                o.put("rankName", "正常");
                                o.put("score", x.getValue());
                                o.put("statement",
                                        String.format("%s的本次结果为正常，请您继续保持。暂未发现需要关注的风险内容。如身体感到明显不适，请及早进行专业的健康指导或医疗服务。"
                                                , x.getName()));
                                systemAssessmentArray.add(o);
                            });
                }
            }
            //生化检测的数据
            JSONObject biochemical = new JSONObject();
            biochemical.put("name", "生化检测");
            Map<String, List<ReportDataScoreDto>> biochemicalDtoMap = reportDataScoreDtoList.stream().filter(x -> biochemicalList.contains(x.getNameEn()))
                    .collect(Collectors.groupingBy(ReportDataScoreDto::getNameEn));
            JSONArray biochemicalArray = new JSONArray();
            biochemicalDtoMap.forEach((k, v) -> {
                JSONObject o = new JSONObject();
                o.put("focus", (int) v.stream().filter(x -> x.getInspectResult() == 0).count());
                o.put("name", v.get(0).getName());
                o.put("nameEn", v.get(0).getNameEn());
                biochemicalArray.add(o);
            });
            biochemical.put("value", biochemicalArray);
            //专项检查
            int specialSeriousIllnessCount = (int) reportDataScoreDtoList.stream().filter(x -> x.getIfSeriousIllness() != null && x.getIfSeriousIllness() == 1 && x.getValueRank() != null && x.getValueRank() > 0).count();
            int specialChronics = (int) (int) reportDataScoreDtoList.stream().filter(x -> x.getIfChronicDisease() != null && x.getIfChronicDisease() == 1 && x.getValueRank() != null && x.getValueRank() > 0).count();
            int specialCancer = (int) (int) reportDataScoreDtoList.stream().filter(x -> x.getIfCancerExam() != null && x.getIfCancerExam() == 1 && x.getValueRank() != null && x.getValueRank() > 0).count();

            JSONArray specialArray = new JSONArray();
            JSONObject s0 = new JSONObject();
            s0.put("name", "一般检查");
            s0.put("nameEn", "normalExam");
            s0.put("focus", 0);
            JSONObject s1 = new JSONObject();
            s1.put("name", "大病筛查");
            s1.put("nameEn", "seriousIllnessExam");
            s1.put("focus", specialSeriousIllnessCount);
            JSONObject s2 = new JSONObject();
            s2.put("name", "慢病检测");
            s2.put("nameEn", "chronicsExam");
            s2.put("focus", specialChronics);
            JSONObject s3 = new JSONObject();
            s3.put("name", "癌症筛查");
            s3.put("nameEn", "cancerExam");
            s3.put("focus", specialCancer);
            specialArray.add(s0);
            specialArray.add(s1);
            specialArray.add(s2);
            specialArray.add(s3);
            JSONObject special = new JSONObject();
            special.put("name", "专项检测");
            special.put("value", specialArray);


            result.put("biochemical", biochemical);
            result.put("specialmical", special);
            result.put("systemAssessment", systemAssessmentArray);
            result.put("systemRadar", systemRadar);
        }
        return result;
    }

    public Object getMedicalReportDataDetail(String openId, String organ, String version) {
        List<String> mainSystemList = Lists.newArrayList("sysBrain", "sysCardiac", "sysEndocrin", "sysRespiratory", "sysDigestive",
                "sysHepatobiliary", "sysUrinary", "sysIntestinal", "sysGynecological");
        List<String> biochemicalList = Lists.newArrayList("bioImmunobiochemistry", "bioBloodGlucose", "bioBlood", "bioThyroid", "bioUrinary", "bioTumor");
        List<String> specialExamList = Lists.newArrayList("normalExam", "seriousIllnessExam", "chronicsExam", "cancerExam");

        List<ReportRecord> reportRecord = reportRecordService.getReportRecordByOpenId(openId, version, 1);
        if (CollUtil.isEmpty(reportRecord)) {
            return new JSONObject();
        }

        String reportId = reportRecord.get(0).getId();
        String reportVersion = version;
        if (StringUtils.isNotBlank(reportRecord.get(0).getVersion())) {
            if (StringUtils.isBlank(version)) {
                reportVersion = reportRecord.get(0).getVersion();
            }
        } else {
            log.info("最新记录 version 不存在：'{}", openId);
        }
        if (mainSystemList.contains(organ)) {
            JSONObject result = new JSONObject();
            List<ReportDataSystemScoreDto> reportDataSystemScoreDtoList =
                    reportDataService.getReportDataSystemScoreDtoByReportId(reportId, organ);
            if (CollUtil.isNotEmpty(reportDataSystemScoreDtoList)) {
                JSONArray diseaseRiskArray = new JSONArray();
                reportDataSystemScoreDtoList.forEach(x -> {
                    JSONObject o = new JSONObject();
                    o.put("checked", false);
                    o.put("name", x.getItemName());
                    o.put("rank", x.getValueRank());
                    o.put("rankHighLimit", "0");
                    o.put("rankLowLimit", "正常");
                    o.put("rankName", levelDescribe(x.getValueRank() + ""));
                    o.put("rankNum", 6);
                    o.put("rulerValue", x.getValueA());
                    diseaseRiskArray.add(o);
                });
                result.put("diseaseRisk", diseaseRiskArray);
                //
                result.put("itemName", reportDataSystemScoreDtoList.get(0).getSystemName() + "评估");
                //
                JSONArray organRiskArray = new JSONArray();
                reportDataSystemScoreDtoList.stream().sorted((x1, x2) -> x2.getValueRank() - x1.getValueRank())
                        .collect(Collectors.toMap(ReportDataSystemScoreDto::getOrganName, reportDataSystemScoreDto -> reportDataSystemScoreDto, (x1, x2) -> x1))
                        .forEach((k, v) -> {
                            JSONObject o = new JSONObject();
                            o.put("name", v.getOrganName());
                            o.put("rank", v.getValueRank());
                            o.put("rankName", levelDescribe(v.getValueRank() + ""));
                            organRiskArray.add(o);
                        });
                result.put("organRisk", organRiskArray);
                //
                result.put("rank", reportDataSystemScoreDtoList.get(0).getScoreRank());
                //
                result.put("rankName", levelDescribe(reportDataSystemScoreDtoList.get(0).getScoreRank() + ""));
                //
                result.put("statement", reportDataSystemScoreDtoList.get(0).getStatement());
            }
            return result;
        } else if (specialExamList.contains(organ)) {
            JSONArray resultArray = new JSONArray();
            if ("cancerExam".equals(organ)) {
                JSONObject result = new JSONObject();
                result.put("itemName", "癌症筛查");
                result.put("value", reportDataService.getReportDataCancerDtoList(reportId));
                resultArray.add(result);
            }
            if ("chronicsExam".equals(organ)) {
                JSONObject result = new JSONObject();
                result.put("itemName", "慢病检测");
                result.put("value", reportDataService.getReportDataChronicsDtoList(reportId));
                resultArray.add(result);
            }
            if ("seriousIllnessExam".equals(organ)) {
                JSONObject o0 = new JSONObject();
                o0.put("itemName", "脑梗早筛");
                o0.put("value", reportDataService.getReportDataBrainDtoList(reportId));
                JSONObject o1 = new JSONObject();
                o1.put("itemName", "心梗早筛");
                o1.put("value", reportDataService.getReportDataHeartDtoList(reportId));
                resultArray.add(o0);
                resultArray.add(o1);
            }
            if ("normalExam".equals(organ)) {
                List<ReportDataNormalDto> reportDataNormalDtoList = reportDataService.getReportDataNormalDtoList(reportId);
                if (CollUtil.isNotEmpty(reportDataNormalDtoList)) {
                    JSONArray valueArray = new JSONArray();
                    JSONObject o0 = new JSONObject();
                    o0.put("highLight", 0);
                    o0.put("name", "身高");
                    o0.put("range", null);
                    o0.put("score", reportDataNormalDtoList.get(0).getHeight());
                    JSONObject o1 = new JSONObject();
                    o1.put("highLight", 0);
                    o1.put("name", "体重");
                    o1.put("range", null);
                    o1.put("score", reportDataNormalDtoList.get(0).getWeight());
                    JSONObject o2 = new JSONObject();
                    o2.put("highLight", 0);
                    o2.put("name", "体重指数");
                    o2.put("range", "18.5-23.9");
                    o2.put("score", reportDataNormalDtoList.get(0).getBmi());
                    valueArray.add(o0);
                    valueArray.add(o1);
                    valueArray.add(o2);
                    resultArray.add(valueArray);
                }
            }
            return resultArray;
        } else if (biochemicalList.contains(organ)) {
            JSONArray resultArray = new JSONArray();
            List<ReportDataBioDto> reportDataBioDtoList = reportDataService.getReportDataBioDtoList(reportId, organ);
            if (CollUtil.isNotEmpty(reportDataBioDtoList)) {
                JSONObject result = new JSONObject();
                result.put("itemName", reportDataBioDtoList.get(0).getSystemName());
                result.put("value", reportDataBioDtoList);
                resultArray.add(result);
            }
            return resultArray;
        }
        return new JSONObject();
    }

    public JSONObject showVitalSignsDetail(String openId, String startDate, String endDate, String signType, String dateType) {
        if ("1".equals(signType)) {
            if ("1".equals(dateType)) {
                JSONObject result = new JSONObject();
                LocalDateTime startDateLdt;
                if (StringUtils.isBlank(startDate)) {
                    startDateLdt = LocalDate.now().atStartOfDay();
                } else {
                    startDateLdt = LocalDateTime.parse(startDate + " 00:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                }
                double sum = 0.0;
                JSONArray arrayX = new JSONArray();
                JSONArray arrayXSticker = new JSONArray();
                JSONArray arrayValue = new JSONArray();
                for (LocalDateTime ldt = startDateLdt; ldt.isBefore(startDateLdt.plusDays(1)); ldt = ldt.plusHours(1)) {
                    int hour = ldt.getHour();
                    String hourMin = ldt.format(DateTimeFormatter.ofPattern("HH:mm"));
                    double d = RandomUtil.randomDouble(0, 25);
                    DecimalFormat formatter = new DecimalFormat("#.00");
                    double valueD = Double.parseDouble(formatter.format(d));
                    sum = sum + valueD;
                    arrayX.add(hour);
                    arrayXSticker.add(hourMin);
                    arrayValue.add(valueD);
                }
                JSONObject plotData = new JSONObject();
                plotData.put("value", arrayValue);
                plotData.put("x", arrayX);
                plotData.put("xSticker", arrayXSticker);
                result.put("plotData", plotData);
                result.put("introduction", "血糖是指血液中葡萄糖的含量，属于糖代谢检查，可用于筛查、诊断及监测糖尿病、低血糖症等多种糖代谢异常相关疾病，反映了机体对葡萄糖的吸收、代谢是否正常。血糖主要包括空腹血糖及餐后血糖两个检查指标，检测空腹血糖时患者需要至少禁食8小时以上，一般需隔夜空腹检查血糖，餐后血糖是指从进食第一口食物后开始计算时间至2小时准时抽血测定血糖值。【正常指标】空腹血糖正常值为4.4~6.1mmol/L。餐后1小时血糖正常值为6.7~9.4 mmo/L。餐后2小时血糖 正常值为≤7.8mmolL。");

                JSONObject processData = new JSONObject();
                processData.put("high", 0.7);
                processData.put("highPercent", 0.7);
                processData.put("low", 0.5);
                processData.put("lowPercent", 0.5);
                processData.put("max", 1);
                processData.put("min", 0);
                processData.put("result", "血糖正常");
                processData.put("valuePercent", 0.6);
                result.put("processData", processData);

                double d = sum / 24.0;
                DecimalFormat formatter = new DecimalFormat("#.00");
                double valueD = Double.parseDouble(formatter.format(d));
                result.put("avgValue", valueD);
                return result;
            } else if ("2".equals(dateType)) {
                JSONObject result = new JSONObject();
                LocalDate startLd;
                LocalDate endLd;
                if (StringUtils.isNotBlank(startDate)) {
                    if (StringUtils.isNotBlank(endDate)) {
                        startLd = LocalDate.parse(startDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                        endLd = LocalDate.parse(endDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                    } else {
                        startLd = LocalDate.parse(startDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                        endLd = startLd.plusDays(6).isAfter(LocalDate.now()) ? LocalDate.now() : startLd.plusDays(7);
                    }
                } else {
                    if (StringUtils.isNotBlank(endDate)) {
                        endLd = LocalDate.parse(endDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                        startLd = endLd.minusDays(6);
                    } else {
                        endLd = LocalDate.now();
                        startLd = endLd.minusDays(6);
                    }
                }
                double sum = 0.0;
                JSONArray arrayX = new JSONArray();
                JSONArray arrayXSticker = new JSONArray();
                JSONArray arrayValue = new JSONArray();
                int x = 0;
                for (LocalDate ld = startLd; ld.isBefore(endLd); ld = ld.plusDays(1)) {

                    String hourMin = ld.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.CHINESE);
                    double d = RandomUtil.randomDouble(0, 25);
                    DecimalFormat formatter = new DecimalFormat("#.00");
                    double valueD = Double.parseDouble(formatter.format(d));
                    sum = sum + valueD;
                    arrayX.add(x);
                    arrayXSticker.add(hourMin);
                    arrayValue.add(valueD);
                    x = x + 1;
                }
                JSONObject plotData = new JSONObject();
                plotData.put("value", arrayValue);
                plotData.put("x", arrayX);
                plotData.put("xSticker", arrayXSticker);
                result.put("plotData", plotData);
                result.put("introduction", "血糖是指血液中葡萄糖的含量，属于糖代谢检查，可用于筛查、诊断及监测糖尿病、低血糖症等多种糖代谢异常相关疾病，反映了机体对葡萄糖的吸收、代谢是否正常。血糖主要包括空腹血糖及餐后血糖两个检查指标，检测空腹血糖时患者需要至少禁食8小时以上，一般需隔夜空腹检查血糖，餐后血糖是指从进食第一口食物后开始计算时间至2小时准时抽血测定血糖值。【正常指标】空腹血糖正常值为4.4~6.1mmol/L。餐后1小时血糖正常值为6.7~9.4 mmo/L。餐后2小时血糖 正常值为≤7.8mmolL。");

                JSONObject processData = new JSONObject();
                processData.put("high", 0.7);
                processData.put("highPercent", 0.7);
                processData.put("low", 0.5);
                processData.put("lowPercent", 0.5);
                processData.put("max", 1);
                processData.put("min", 0);
                processData.put("result", "血糖正常");
                processData.put("valuePercent", 0.6);
                result.put("processData", processData);

                double d = sum / 24.0;
                DecimalFormat formatter = new DecimalFormat("#.00");
                double valueD = Double.parseDouble(formatter.format(d));
                result.put("avgValue", valueD);
                return result;
            } else if ("3".equals(dateType)) {
                JSONObject result = new JSONObject();
                LocalDate startLd;
                LocalDate endLd;
                if (StringUtils.isNotBlank(startDate)) {
                    if (StringUtils.isNotBlank(endDate)) {
                        startLd = LocalDate.parse(startDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                        endLd = LocalDate.parse(endDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                    } else {
                        startLd = LocalDate.parse(startDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                        endLd = startLd.withDayOfMonth(startLd.lengthOfMonth());
                    }
                } else {
                    if (StringUtils.isNotBlank(endDate)) {
                        endLd = LocalDate.parse(endDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                        startLd = endLd.withDayOfMonth(1);
                    } else {
                        startLd = LocalDate.now().withDayOfMonth(1);
                        endLd = LocalDate.now().withDayOfMonth(LocalDate.now().lengthOfMonth());
                    }
                }
                double sum = 0.0;
                JSONArray arrayX = new JSONArray();
                JSONArray arrayXSticker = new JSONArray();
                JSONArray arrayValue = new JSONArray();
                int x = 0;
                for (LocalDate ld = startLd; !ld.isAfter(endLd); ld = ld.plusDays(1)) {

                    String hourMin = ld.format(DateTimeFormatter.ofPattern("MM/dd"));
                    double d = RandomUtil.randomDouble(0, 25);
                    DecimalFormat formatter = new DecimalFormat("#.00");
                    double valueD = Double.parseDouble(formatter.format(d));
                    sum = sum + valueD;
                    arrayX.add(x);
                    arrayXSticker.add(hourMin);
                    arrayValue.add(valueD);
                    x = x + 1;
                }
                JSONObject plotData = new JSONObject();
                plotData.put("value", arrayValue);
                plotData.put("x", arrayX);
                plotData.put("xSticker", arrayXSticker);
                result.put("plotData", plotData);
                result.put("introduction", "血糖是指血液中葡萄糖的含量，属于糖代谢检查，可用于筛查、诊断及监测糖尿病、低血糖症等多种糖代谢异常相关疾病，反映了机体对葡萄糖的吸收、代谢是否正常。血糖主要包括空腹血糖及餐后血糖两个检查指标，检测空腹血糖时患者需要至少禁食8小时以上，一般需隔夜空腹检查血糖，餐后血糖是指从进食第一口食物后开始计算时间至2小时准时抽血测定血糖值。【正常指标】空腹血糖正常值为4.4~6.1mmol/L。餐后1小时血糖正常值为6.7~9.4 mmo/L。餐后2小时血糖 正常值为≤7.8mmolL。");

                JSONObject processData = new JSONObject();
                processData.put("high", 0.7);
                processData.put("highPercent", 0.7);
                processData.put("low", 0.5);
                processData.put("lowPercent", 0.5);
                processData.put("max", 1);
                processData.put("min", 0);
                processData.put("result", "血糖正常");
                processData.put("valuePercent", 0.6);
                result.put("processData", processData);

                double d = sum / 24.0;
                DecimalFormat formatter = new DecimalFormat("#.00");
                double valueD = Double.parseDouble(formatter.format(d));
                result.put("avgValue", valueD);
                return result;
            }
        }
        return new JSONObject();
    }

    private String levelDescribe(String level) {
        Map<String, String> map = Maps.newHashMap();
        map.put("0", "正常");
        map.put("1", "亚健康");
        map.put("2", "发展趋势");
        map.put("3", "潜在风险");
        map.put("4", "需重视");
        map.put("5", "严重风险");
        return map.get(level);
    }

    public File generateReport() {
        return null;
    }

    private String levelDetail(String level) {
        Map<String, String> map = Maps.newHashMap();
        map.put("1", "处于亚健康状态");
        map.put("2", "存在发展趋势");
        map.put("3", "具有潜在风险");
        map.put("4", "需要引起重视");
        map.put("5", "在严重风险");
        return map.get(level);

    }

    public JSONObject getHealthReportData(String openId, String version) {
        JSONObject result = new JSONObject();
        ReportRecord reportRecord = reportRecordService.getRobotReportRecordByOpenId(openId, version, 2);
        String reportId = reportRecord.getId();
        String reportVersion = version;
        if (StringUtils.isNotBlank(reportRecord.getVersion())) {
            if (StringUtils.isBlank(version)) {
                reportVersion = reportRecord.getVersion();
            }
        } else {
            log.info("最新记录 version 不存在：'{}", openId);
        }
        ReportUserDto reportUserDto = reportRecordService.getReportByUser(openId, reportVersion);
        result.put("age", reportUserDto.getAge());
        result.put("gender", reportUserDto.getGender());
        result.put("name", reportUserDto.getName());
        result.put("time", reportUserDto.getInspectDate());

        List<RobotKnowledgeBaseDto> robotKnowledgeBaseDtos = reportDataRobotService.getRobotKnowledgeBaseDtoDtoByReportId(reportId);
        // 创建器官系统功能分组的JSON数组
        JSONArray organFunctionArray = new JSONArray();
        // 创建营养与身体分组的JSON数组
        JSONArray nutritionBodyArray = new JSONArray();

        // 遍历对象集合，根据systemName属性进行分组
        for (RobotKnowledgeBaseDto object : robotKnowledgeBaseDtos) {
            String systemName = object.getSystemName();
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("systemName", systemName);
            jsonObject.put("partName", object.getPartName());
            jsonObject.put("partNameEn", object.getPartNameEn());
            if ("器官系统功能".equals(systemName)) {
                organFunctionArray.add(jsonObject);
            } else if ("营养与身体".equals(systemName)) {
                nutritionBodyArray.add(jsonObject);
            }
        }
        // 将分组结果放入result JSON对象
        result.put("器官系统功能健康", organFunctionArray);
        result.put("营养与身体健康", nutritionBodyArray);
        //
        JSONObject healthData = new JSONObject();
        JSONObject organFunctionObj = new JSONObject();
        organFunctionObj.put("name", "器官系统功能健康");
        organFunctionObj.put("nameEn", "organFunction");
        organFunctionObj.put("data", organFunctionArray);

        JSONObject nutritionBodyObj = new JSONObject();
        nutritionBodyObj.put("name", "营养与身体健康");
        nutritionBodyObj.put("nameEn", "nutritionBody");
        nutritionBodyObj.put("data", nutritionBodyArray);
        healthData.put("organFunction", organFunctionObj);
        healthData.put("nutritionBody", nutritionBodyObj);
        result.put("healthData", healthData);
        return result;
    }

    public JSONObject getHealthReportDataV2(String openId, String version) {
        JSONObject result = new JSONObject();
        ReportRecord reportRecord = reportRecordService.getRobotReportRecordByOpenId(openId, version, 3);
        String reportId = reportRecord.getId();
        String reportVersion = version;
        if (StringUtils.isNotBlank(reportRecord.getVersion())) {
            if (StringUtils.isBlank(version)) {
                reportVersion = reportRecord.getVersion();
            }
        } else {
            log.info("最新记录 version 不存在：'{}", openId);
        }
        ReportUserDto reportUserDto = reportRecordService.getReportByUser(openId, reportVersion);
        result.put("age", reportUserDto.getAge());
        result.put("gender", reportUserDto.getGender());
        result.put("name", reportUserDto.getName());
        result.put("time", reportUserDto.getInspectDate());

        List<RobotKnowledgeBaseDto> robotKnowledgeBaseDtos = reportDataRobotService.getRobotKnowledgeBaseDtoDtoByReportId(reportId);
        // 创建器官系统功能分组的JSON数组
        JSONArray organFunctionArray = new JSONArray();
        // 创建营养与身体分组的JSON数组
        JSONArray nutritionBodyArray = new JSONArray();

        // 遍历对象集合，根据systemName属性进行分组
        Map<String, List<RobotKnowledgeBaseDto>> robotSystemMap = robotKnowledgeBaseDtos.stream().collect(Collectors.groupingBy(RobotKnowledgeBaseDto::getSystemName));
        LinkedHashMap<String, JSONObject> healthData = new LinkedHashMap<>();
        robotSystemMap.forEach((k,v)->{
            if (v!= null && v.size()>0){
                JSONObject systemObject = new JSONObject();
                JSONArray systemArray = new JSONArray();
                for (RobotKnowledgeBaseDto robotKnowledgeBaseDto : v) {
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("systemName", robotKnowledgeBaseDto.getSystemName());
                    jsonObject.put("partName", robotKnowledgeBaseDto.getPartName());
                    jsonObject.put("partNameEn", robotKnowledgeBaseDto.getPartNameEn());
                    systemArray.add(jsonObject);
                }
                systemObject.put("name", v.get(0).getSystemName());
                systemObject.put("nameEn", v.get(0).getSystemNameEn());
                systemObject.put("data", systemArray);
                switch (v.get(0).getSystemName()){
                    case "器官系统功能":
                        systemObject.put("index", 0);
                        break;
                    case "骨与关节":
                        systemObject.put("index", 1);
                        break;
                    case "营养与身体":
                        systemObject.put("index", 2);
                        break;
                    case "生殖":
                        systemObject.put("index", 3);
                        break;
                    case "特殊":
                        systemObject.put("index", 4);
                        break;
                    default:
                        log.info("其他类别：{}", v.get(0).getSystemName());
                        systemObject.put("index", 9);
                }
                healthData.put(v.get(0).getSystemNameEn(), systemObject);
            }
        });
        List<Map.Entry<String, JSONObject>> list = new ArrayList<>(healthData.entrySet());
        Collections.sort(list, new Comparator<Map.Entry<String, JSONObject>>() {
            public int compare(Map.Entry<String, JSONObject> o1, Map.Entry<String, JSONObject> o2) {
                return o1.getValue().getInteger("index") - o2.getValue().getInteger("index");
            }
        });
        Map<String, JSONObject> linkedHashMap = new LinkedHashMap<>();
        for (Map.Entry<String, JSONObject> entry : list) {
            linkedHashMap.put(entry.getKey(), entry.getValue());
        }
        result.put("healthData", linkedHashMap);
        return result;
    }


    public List<RobotReportDataDto> getReportDataRobotDetail(String openId, String partNameEn, String version, String packageType) {
        Integer type = null;
        if (StringUtils.isBlank(packageType)){
            type = 2;
        }else {
            type = Integer.parseInt(packageType);
        }
        ReportRecord reportRecord = reportRecordService.getRobotReportRecordByOpenId(openId, version, type);
        if (reportRecord == null) {
            log.info("最新记录 version 不存在：'{}", openId);
            return Collections.emptyList();
        }

        String reportId = reportRecord.getId();
        String reportVersion = StringUtils.isNotBlank(reportRecord.getVersion()) ?
                (StringUtils.isBlank(version) ? reportRecord.getVersion() : version) :
                null;

        List<ReportDataRobotDetailDto> reportDataRobotDetailDtoList = reportDataRobotService.getReportDataRobotDetailDtoDtoByReportId(reportId, partNameEn);
        List<RobotReportDataDto> robotReportDataDtoList = new ArrayList<>();

        for (ReportDataRobotDetailDto reportDataRobotDetailDto : reportDataRobotDetailDtoList) {
            RobotReportDataDto robotReportDataDto = new RobotReportDataDto();
            robotReportDataDto.setPartName(reportDataRobotDetailDto.getPartName());
            robotReportDataDto.setItemName(reportDataRobotDetailDto.getItemName());
            robotReportDataDto.setContent(reportDataRobotDetailDto.getContent());
            robotReportDataDto.setAdvice(reportDataRobotDetailDto.getAdvice());
            double number = Double.parseDouble(reportDataRobotDetailDto.getValue());
            robotReportDataDto.setValue(number < 0 ? "0" : reportDataRobotDetailDto.getValue());
            robotReportDataDto.setType(reportDataRobotDetailDto.getType());
            robotReportDataDto.setNormalRank(reportDataRobotDetailDto.getNormalRank());
            robotReportDataDto.setRiskRank1(reportDataRobotDetailDto.getRiskRank1());
            robotReportDataDto.setRiskRank2(reportDataRobotDetailDto.getRiskRank2());
            robotReportDataDto.setRiskRank3(reportDataRobotDetailDto.getRiskRank3());

            switch (ReportDataType.values()[reportDataRobotDetailDto.getType() - 1]) {
                case TYPE_1:
                    setRiskValueForType1(robotReportDataDto, reportDataRobotDetailDto);
                    break;
                case TYPE_2:
                    setRiskValueForType2(robotReportDataDto, reportDataRobotDetailDto);
                    break;
                case TYPE_3:
                    setRiskValueForType3(robotReportDataDto, reportDataRobotDetailDto);
                    break;
                default:
                    break;
            }

            robotReportDataDtoList.add(robotReportDataDto);
        }

        return robotReportDataDtoList;
    }

    private void setRiskValueForType1(RobotReportDataDto robotReportDataDto, ReportDataRobotDetailDto reportDataRobotDetailDto) {
        String[] bounds = StringUtils.split(reportDataRobotDetailDto.getNormalRank(), " - ");
        double lowerBound = Double.parseDouble(bounds[0]);
        double upperBound = Double.parseDouble(bounds[1]);

        String[] bounds1 = StringUtils.split(reportDataRobotDetailDto.getRiskRank1(), " - ");
        double lowerBound1 = Double.parseDouble(bounds1[0]);
        double upperBound1 = Double.parseDouble(bounds1[1]);

        String[] bounds2 = StringUtils.split(reportDataRobotDetailDto.getRiskRank2(), " - ");
        double lowerBound2 = Double.parseDouble(bounds2[0]);
        double upperBound2 = Double.parseDouble(bounds2[1]);

        double threshold = Double.parseDouble(reportDataRobotDetailDto.getRiskRank3().trim().substring(1));

        String symbol = "";

        String riskRank3 = reportDataRobotDetailDto.getRiskRank3().trim();
        if (riskRank3.contains("＜")) {
            symbol = "<";
        } else if (riskRank3.contains("＞")) {
            symbol = ">";
        }

        double value = Double.parseDouble(reportDataRobotDetailDto.getValue());

        if (value >= lowerBound && value <= upperBound) {
            robotReportDataDto.setRiskValueRank(reportDataRobotDetailDto.getNormalRank());
            robotReportDataDto.setRiskValue("正常");
        } else if (value >= lowerBound1 && value <= upperBound1) {
            robotReportDataDto.setRiskValueRank(reportDataRobotDetailDto.getRiskRank1());
            robotReportDataDto.setRiskValue("轻度异常");
        } else if (value >= lowerBound2 && value <= upperBound2) {
            robotReportDataDto.setRiskValueRank(reportDataRobotDetailDto.getRiskRank2());
            robotReportDataDto.setRiskValue("中度异常");
        } else if (symbol.equals("<") && value < threshold) {
            robotReportDataDto.setRiskValueRank(reportDataRobotDetailDto.getRiskRank3());
            robotReportDataDto.setRiskValue("重度异常");
        } else if (symbol.equals(">") && value > threshold) {
            robotReportDataDto.setRiskValueRank(reportDataRobotDetailDto.getRiskRank3());
            robotReportDataDto.setRiskValue("重度异常");
        }
    }

    private void setRiskValueForType2(RobotReportDataDto robotReportDataDto, ReportDataRobotDetailDto reportDataRobotDetailDto) {
        String[] bounds = StringUtils.split(reportDataRobotDetailDto.getNormalRank(), " - ");
        double lowerBound = Double.parseDouble(bounds[0]);
        double upperBound = Double.parseDouble(bounds[1]);

        double riskRank1 = Double.parseDouble(reportDataRobotDetailDto.getRiskRank1().substring(1));
        double riskRank2 = Double.parseDouble(reportDataRobotDetailDto.getRiskRank2().substring(1));

        double value = Double.parseDouble(reportDataRobotDetailDto.getValue());

        if (value >= lowerBound && value <= upperBound) {
            robotReportDataDto.setRiskValueRank(reportDataRobotDetailDto.getNormalRank());
            robotReportDataDto.setRiskValue("正常");
        } else if (value > riskRank1) {
            robotReportDataDto.setRiskValueRank(reportDataRobotDetailDto.getRiskRank1());
            robotReportDataDto.setRiskValue("偏大");
        } else if (value < riskRank2) {
            robotReportDataDto.setRiskValueRank(reportDataRobotDetailDto.getRiskRank2());
            robotReportDataDto.setRiskValue("偏小");
        }
    }

    private static final String REGEX_NUMBER = "[<|>]?-?\\d+(\\.\\d+)?";

    private void setRiskValueForType3(RobotReportDataDto robotReportDataDto, ReportDataRobotDetailDto reportDataRobotDetailDto) {
        String normalRank = reportDataRobotDetailDto.getNormalRank().trim();
        String value = robotReportDataDto.getValue();

        // 使用正则表达式提取符号和数字
        Pattern pattern = Pattern.compile(REGEX_NUMBER);
        Matcher symbolMatcher = pattern.matcher(normalRank);
        Matcher valueMatcher = pattern.matcher(value);

        String symbol = "";
        double number = 0.0;
        double value1 = 0.0;

        if (normalRank.contains("<")) {
            symbol = "<";
        } else if (normalRank.contains(">")) {
            symbol = ">";
        }

        while (symbolMatcher.find()) {
            number = Double.parseDouble(symbolMatcher.group());
        }

        while (valueMatcher.find()) {
            value1 = Double.parseDouble(valueMatcher.group());
        }

        // 判断符号和数值
        RiskLevel riskLevel = null;
        if (symbol.equals("<")) {
            riskLevel = value1 < number ? RiskLevel.NORMAL : RiskLevel.EXCEPTION;
        } else if (symbol.equals(">")) {
            riskLevel = value1 > number ? RiskLevel.NORMAL : RiskLevel.EXCEPTION;
        } else if (normalRank.contains("-")) {
            double value2 = Double.parseDouble(value.replace("%", "")) / 100.0;
            String[] range = normalRank.split("-");
            double lowerBound = Double.parseDouble(range[0].replace("%", "")) / 100.0;
            double upperBound = Double.parseDouble(range[1].replace("%", "")) / 100.0;

            riskLevel = value2 >= lowerBound && value2 <= upperBound ? RiskLevel.NORMAL : RiskLevel.EXCEPTION;
        } else if (normalRank.equals(value)) {
            riskLevel = RiskLevel.NORMAL;
        } else {
            riskLevel = RiskLevel.EXCEPTION;
        }

        robotReportDataDto.setRiskValueRank(reportDataRobotDetailDto.getNormalRank());
        robotReportDataDto.setRiskValue(riskLevel.getValue());
    }

    public List<HealthIndicatorInfo> getHealthIndicatorList(){




        return healthIndicatorInfoService.list();
    }

}
